package com.shuhe.domain.mxgc;

import com.shuhe.common.MyDateUtils;
import com.shuhe.common.Tools;
import com.shuhe.metastore.DBSql;
import com.shuhe.metastore.MetaMysql;
import org.quartz.CronExpression;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;

import static com.shuhe.JettyServer.globalProperties;
import static com.shuhe.common.CommonFunction.closeDb;
import static com.shuhe.domain.mxgc.TaskExecute.taskExceute;
import static com.shuhe.handler.DataInHandler.strDateFormat;


public class TaskMxgc {
    private static final Logger LOG = LoggerFactory.getLogger(TaskMxgc.class);

    public TaskMxgc(String bz, String pcid, String cTime) throws Exception {
        Connection metaConn = null;
        Connection dbConn = null;
        try {
            metaConn = MetaMysql.connect();
            dbConn = DBSql.connect();
            int xh = 0;
            //待执行所有任务 1
            String sql = "SELECT a.*,CASE WHEN b.task_id IS NULL THEN 'noCron' ELSE 'cron' END ifcron,b.task_cron " +
                    "FROM (\n" +
                    "SELECT a.task_id,a.task_name,a.mx_id,b.db_name,b.table_name,b.sql_content FROM mxgc_user_task a," +
                    "mxgc_user_table b  \n" +
                    "WHERE a.mx_id=b.mxid AND a.STATUS='run' ) a \n" +
                    "LEFT JOIN mxgc_user_task_cron_config b ON a.task_id=b.task_id";
            ArrayList<TaskTableBean> tasks = new ArrayList<>();
            ResultSet rs = MetaMysql.querySql(metaConn, sql);
            while (rs.next()) {
                TaskTableBean taskTableBean = new TaskTableBean();
                taskTableBean.setTaskId(rs.getString("task_id"));
                taskTableBean.setTaskName(rs.getString("task_name"));
                taskTableBean.setMxId(rs.getString("mx_id"));
                taskTableBean.setDb(rs.getString("db_name"));
                taskTableBean.setTableName(rs.getString("table_name"));
                taskTableBean.setSqlContent(rs.getString("sql_content"));
                taskTableBean.setXh(xh);
                Boolean ifRun = getIfRun(metaConn, rs.getString("ifcron"), rs.getString("task_cron"),
                        cTime, rs.getString("task_id"));
                if (ifRun) {
                    tasks.add(taskTableBean);
                }
            }
            //任务依赖表
            sql = "select dest_table,task_id,input_tables_cf,case when b.is_write='y' then 'zy' else 'common' end " +
                    "last_table_type " +
                    "from v_mxgc_user_task_tables  a left join mxgc_user_dbs b " +
                    "on substr(a.input_tables_cf,1,instr(a.input_tables_cf,'.')-1)=b.db_name\n";
            rs = MetaMysql.querySql(metaConn, sql);
            ArrayList<TaskTableBean> destTasks = new ArrayList<>();
            while (rs.next()) {
                TaskTableBean taskTableBean = new TaskTableBean();
                taskTableBean.setDestTable(rs.getString("dest_table"));
                taskTableBean.setTaskId(rs.getString("task_id"));
                taskTableBean.setInputTablesCf(rs.getString("input_tables_cf"));
                taskTableBean.setLastTableType(rs.getString("last_table_type"));
                destTasks.add(taskTableBean);
            }

            //1循环更新序号
            for (int i = 0; i < tasks.size(); i++) {
                xh = methodMain(tasks.get(i), destTasks, tasks, xh);
            }
            //2按序号升序排序tasks
            Collections.sort(tasks, new Comparator<TaskTableBean>() {
                public int compare(TaskTableBean p1, TaskTableBean p2) {
                    return Integer.compare(p1.getXh(), p2.getXh());
                }
            });
            //3任务按顺序执行
            for (int i = 0; i < tasks.size(); i++) {
                taskExceute(metaConn, dbConn, pcid, tasks.get(i).getTaskId(), tasks.get(i).getDb(),
                        tasks.get(i).getTableName(), tasks.get(i).getSqlContent(), "cronExce");
            }
        } finally {
            closeDb(metaConn);
            closeDb(dbConn);
        }
    }

    public static Boolean getIfRan(Connection metaConn, String taskId, String cTime) throws Exception {
        Boolean ifRan = false;
        String sql = "select count(*) cun from mxgc_user_task_log where qssj>='" + cTime.substring(0, 10)
                + "' and task_id='" + taskId + "'";
        ResultSet rs = MetaMysql.querySql(metaConn, sql);
        if (rs.next()) {
            if (!rs.getString("cun").equals("0")) {
                ifRan = true;
            }
        }
        return ifRan;
    }

    public static Boolean getIfRun(Connection metaConn, String ifcron, String task_cron, String cTime, String taskId) throws Exception {
        Boolean ifRun = false;
        if (ifcron.equals("noCron")) {
            ifRun = true;
        } else {
            Boolean ifRunCron = cronIf(task_cron, cTime);
            Boolean ifRan = getIfRan(metaConn, taskId, cTime);
            if (!ifRan && ifRunCron) {
                ifRun = true;
            }
        }
        return ifRun;
    }


    // 任务串解析
    private static boolean cronIf(String runCron, String cTime) throws Exception {
        boolean cronIf = false;

        CronExpression cron = new CronExpression(runCron);
        Date nextExecutionTime = cron.getNextValidTimeAfter(strDateFormat(MyDateUtils.getBeforeMinuteBydate(cTime,
                -3)));
        //任务运行节点
        if (strDateFormat(cTime).compareTo(nextExecutionTime) > 0) {
            cronIf = true;
        }
        return cronIf;
    }

    public static int methodMain(TaskTableBean task, ArrayList<TaskTableBean> destTasks,
                                 ArrayList<TaskTableBean> tasks, int xh) throws Exception {
        //清单１
        int bz = 0;
        ArrayList<TaskTableBean> destTasksParts = new ArrayList<>();
        for (int i = 0; i < destTasks.size(); i++) {
            if (destTasks.get(i).getTaskId().equals(task.getTaskId()) && destTasks.get(i).getLastTableType().equals(
                    "zy")) {
                destTasksParts.add(destTasks.get(i));
            }
        }
        bz = destTasksParts.size();
        if (bz > 0) {
            //递归找清单中的上一个任务  function
            xh = taskSearch(task, destTasks, tasks, xh);
        } else {
            //序号funtion
            //xh += 1;
            xh = setXh(task, tasks, xh);
        }
        return xh;
    }

    public static int setXh(TaskTableBean task, ArrayList<TaskTableBean> tasks, int xh) throws Exception {
        for (int i = 0; i < tasks.size(); i++) {
            if (tasks.get(i).getTaskId().equals(task.getTaskId())) {
                if (tasks.get(i).getXh() == 0) {
                    xh += 1;
                    tasks.get(i).setXh(xh);
                }
            }
        }
        return xh;
    }

    public static int taskSearch(TaskTableBean task, ArrayList<TaskTableBean> destTasks,
                                 ArrayList<TaskTableBean> tasks, int xh) throws Exception {
        ArrayList<TaskTableBean> destTasksParts = new ArrayList<>();
        for (int i = 0; i < destTasks.size(); i++) {
            if (destTasks.get(i).getTaskId().equals(task.getTaskId()) && destTasks.get(i).getLastTableType().equals(
                    "zy")) {
                destTasksParts.add(destTasks.get(i));
            }
        }
        for (int i = 0; i < destTasksParts.size(); i++) {
            xh = getTaskLast(destTasksParts.get(i), destTasks, tasks, xh);
        }
        //序号funtion
        //xh += 1;
        xh = setXh(task, tasks, xh);
        return xh;
    }

    public static int getTaskLast(TaskTableBean destTask, ArrayList<TaskTableBean> destTasks,
                                  ArrayList<TaskTableBean> tasks, int xh) throws Exception {
        int bz = 0;
        ArrayList<TaskTableBean> destTasksParts = new ArrayList<>();
        for (int i = 0; i < destTasks.size(); i++) {
            if (destTasks.get(i).getDestTable().equals(destTask.getInputTablesCf())) {
                destTasksParts.add(destTasks.get(i));
            }
        }
        if (destTasksParts.size() > 0) {
            bz = destTasksParts.size();
            TaskTableBean task = new TaskTableBean();
            if (bz > 0) {
                for (int i = 0; i < destTasks.size(); i++) {
                    if (destTasks.get(i).getDestTable().equals(destTask.getInputTablesCf())) {
                        task = destTasks.get(i);
                    }
                    xh = taskSearch(task, destTasks, tasks, xh);
                }
            } else {
                return xh;
            }
        }
        return xh;
    }

}
